-------------------------------------------------------------------------------
-- Archivo:                         lu.vhdl
-- Fecha de creacion:               13/01/2011
-- Ultima fecha de modificacion:    28/01/2011
-- Diseñador:                       Liliana Andrade
-- Diseño:                          lu
-- Proposito:                       Unidad logica de 4 bits encauzada en cinco
--                                  etapas, realiza operaciones and, or, xor y
--                                  not. Esta  formada  por  4 componentes mlu,
--                                  4 registros y 1 multiplexor
-------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;

entity lu is
	port(
        A_i         : in  std_logic_vector(3 downto 0); -- operandos A
        B_i         : in  std_logic_vector(3 downto 0); -- operandos B
        ALU_OP_i    : in  std_logic_vector(3 downto 0); -- codigo de operacion
        LU_o        : out std_logic_vector(3 downto 0); -- result seleccionado
        CLK         : in std_logic
	);
end lu;

architecture structural of lu is
  
	component mlu
		port(
			X_i         : in  std_logic;
			Y_i         : in  std_logic;
			Z_AND_o     : out std_logic;
			Z_OR_o      : out std_logic;
			Z_XOR_o     : out std_logic;
			Z_NOT_o     : out std_logic
		);
	end component;

	component mux4to1
		port(
			I0_i     	: in std_logic_vector(3 downto 0);
			I1_i     	: in std_logic_vector(3 downto 0);
			I2_i     	: in std_logic_vector(3 downto 0);
			I3_i     	: in std_logic_vector(3 downto 0);
			SEL_i    	: in std_logic_vector(1 downto 0);
			OUTPUT_o 	: out std_logic_vector(3 downto 0)
		);
	end component;

	signal r0_reg   : std_logic_vector(9 downto 0);     --registro 0
	signal r1_reg   : std_logic_vector(11 downto 0);    --registro 1
	signal r2_reg   : std_logic_vector(13 downto 0);    --registro 2
	signal r3_reg   : std_logic_vector(15 downto 0);    --registro 3

	-- cables que comunican hacia r0_reg
	signal w0_wire  : std_logic_vector(9 downto 0);

	-- cables que comunican hacia r1_reg
	signal w1_wire  : std_logic_vector(11 downto 0);

	-- cables que comunican hacia r2_reg
	signal w2_wire  : std_logic_vector(13 downto 0);
  
	-- cables que comunican hacia r3_reg
	signal w3_wire  : std_logic_vector(15 downto 0);

	-- cables de cada mLU
	signal mlu0_wire    : std_logic_vector(3 downto 0);
	signal mlu1_wire    : std_logic_vector(3 downto 0);
	signal mlu2_wire    : std_logic_vector(3 downto 0);
	signal mlu3_wire    : std_logic_vector(3 downto 0);
  
	begin

		MLU0 : mlu port map (
			X_i         => A_i(0),
			Y_i         => B_i(0),
			Z_AND_o     => mlu0_wire(0),
			Z_OR_o      => mlu0_wire(1),
			Z_XOR_o     => mlu0_wire(2),
			Z_NOT_o     => mlu0_wire(3)
		);

		w0_wire(0)      <= mlu0_wire(0);
		w0_wire(1)      <= mlu0_wire(1);
		w0_wire(2)      <= mlu0_wire(2);
		w0_wire(3)      <= mlu0_wire(3);
		w0_wire(4)      <= A_i(1);
		w0_wire(5)      <= B_i(1);
		w0_wire(6)      <= A_i(2);
		w0_wire(7)      <= B_i(2);
		w0_wire(8)      <= A_i(3);
		w0_wire(9)      <= B_i(3);

		MLU1 : mlu port map (
			X_i         => r0_reg(4),
			Y_i         => r0_reg(5),
			Z_AND_o     => mlu1_wire(0),
			Z_OR_o      => mlu1_wire(1),
			Z_XOR_o     => mlu1_wire(2),
			Z_NOT_o     => mlu1_wire(3)
		);

		w1_wire(0)      <= r0_reg(0);
		w1_wire(1)      <= r0_reg(1);
		w1_wire(2)      <= r0_reg(2);
		w1_wire(3)      <= r0_reg(3);
		w1_wire(4)      <= mlu1_wire(0);
		w1_wire(5)      <= mlu1_wire(1);
		w1_wire(6)      <= mlu1_wire(2);
		w1_wire(7)      <= mlu1_wire(3);
		w1_wire(8)      <= r0_reg(6);
		w1_wire(9)      <= r0_reg(7);
		w1_wire(10)     <= r0_reg(8);
		w1_wire(11)     <= r0_reg(9);

		MLU2 : mlu port map (
			X_i         => r1_reg(8),
			Y_i         => r1_reg(9),
			Z_AND_o     => mlu2_wire(0),
			Z_OR_o      => mlu2_wire(1),
			Z_XOR_o     => mlu2_wire(2),
			Z_NOT_o     => mlu2_wire(3)
		);

		w2_wire(0)      <= r1_reg(0);
		w2_wire(1)      <= r1_reg(1);
		w2_wire(2)      <= r1_reg(2);
		w2_wire(3)      <= r1_reg(3);
		w2_wire(4)      <= r1_reg(4);
		w2_wire(5)      <= r1_reg(5);
		w2_wire(6)      <= r1_reg(6);
		w2_wire(7)      <= r1_reg(7);
		w2_wire(8)      <= mlu2_wire(0);
		w2_wire(9)      <= mlu2_wire(1);
		w2_wire(10)     <= mlu2_wire(2);
		w2_wire(11)     <= mlu2_wire(3);
		w2_wire(12)     <= r1_reg(10);
		w2_wire(13)     <= r1_reg(11);

		MLU3 : mlu port map (
			X_i         => r2_reg(12),
			Y_i         => r2_reg(13),
			Z_AND_o     => mlu3_wire(0),
			Z_OR_o      => mlu3_wire(1),
			Z_XOR_o     => mlu3_wire(2),
			Z_NOT_o     => mlu3_wire(3)
		);

		w3_wire(0)      <= r2_reg(0);
		w3_wire(1)      <= r2_reg(4);
		w3_wire(2)      <= r2_reg(8);
		w3_wire(3)      <= mlu3_wire(0);
		w3_wire(4)      <= r2_reg(1);
		w3_wire(5)      <= r2_reg(5);
		w3_wire(6)      <= r2_reg(9);
		w3_wire(7)      <= mlu3_wire(1);
		w3_wire(8)      <= r2_reg(2);
		w3_wire(9)      <= r2_reg(6);
		w3_wire(10)     <= r2_reg(10);
		w3_wire(11)     <= mlu3_wire(2);
		w3_wire(12)     <= r2_reg(3);
		w3_wire(13)     <= r2_reg(7);
		w3_wire(14)     <= r2_reg(11);
		w3_wire(15)     <= mlu3_wire(3);

		mux_lu : mux4to1 port map (
			I0_i        => r3_reg(3 downto 0),
			I1_i        => r3_reg(7 downto 4),
			I2_i        => r3_reg(11 downto 8),
			I3_i        => r3_reg(15 downto 12),
			SEL_i       => ALU_OP_i(1 downto 0),
			OUTPUT_o    => LU_o
		);
  

	carga_registros: process (CLK)
		begin  -- process cargar_en_registros
			if CLK = '1' and CLK'event then
				r0_reg      <= w0_wire;
				r1_reg      <= w1_wire;
				r2_reg      <= w2_wire;
				r3_reg      <= w3_wire;
			end if;
	end process carga_registros;
  
end structural;
